package com.mybatis.sqlsession;

import com.mybatis.config.BoundSql;
import com.mybatis.entity.Configuration;
import com.mybatis.entity.MappedStatement;
import com.mybatis.utils.ClassUtil;
import com.mybatis.utils.GenericTokenParser;
import com.mybatis.utils.ParameterMapping;
import com.mybatis.utils.ParameterMappingTokenHandler;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * 创建人: yyn
 * 创建时间:2021/7/9 22:22
 */
public class SimpleStatementHandler implements StatementHandler {
    private Configuration configuration;

    public SimpleStatementHandler(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public PreparedStatement prepareStatement(MappedStatement mappedStatement, Object... param) throws Exception {
        Connection connection = configuration.getDataSource().getConnection();
        BoundSql boundSql = getBoundSql(mappedStatement.getSql());
        PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
        List<ParameterMapping> parameterMappingList = boundSql.getParameterMappingList();
        Class<?> paramClassType = ClassUtil.getClassType(mappedStatement.getParamType());
        if (param != null && param.length == 1 && paramClassType == Integer.class) {
            preparedStatement.setObject(1,param[0]);
        }else {
            for (int i = 0; i < parameterMappingList.size(); i++) {
                ParameterMapping parameterMapping = parameterMappingList.get(i);
                String content = parameterMapping.getContent();
                //反射
                Field declaredField = paramClassType.getDeclaredField(content);
                //暴力访问
                declaredField.setAccessible(true);
                Object o = declaredField.get(param[0]);

                preparedStatement.setObject(i+1,o);
            }
        }

        return preparedStatement;
    }
    private BoundSql getBoundSql(String sql) {
        ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
        //解析出来的sql
        String parseSql = genericTokenParser.parse(sql);
        //参数名称
        List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();

        return new BoundSql(parseSql,parameterMappings);
    }

}
